﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.Cryptography;

namespace HttpAssiant.Wrapper
{
    public class WrapperUtil
    {
        private static string TAG = "WrapperUtil";

        private static WrapperUtil _instance = null;


        public static WrapperUtil getInstance()
        {
            if (_instance == null)
            {
                _instance = new WrapperUtil();
                if (_instance.CheckApiSign(Const.dllPath))
                {
                    if (_instance.login() < 0)
                    {
                        return null;
                    }
                }
                else
                {
                    return null;
                }
            }
            return _instance;

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="u"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        public int login()
        {
            int rel = Wrapper.uu_login(Const.u,Const.p);
            if(rel<0)
            {
                Log.PrintLog(TAG + " ： 登陆失败，错误原因为:" + rel);
            }
            return rel;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public string recognize(string path)
        {
            //1～3汉字
            int codeType = 2003;
            StringBuilder result = new StringBuilder(50);
            int codeId = Wrapper.uu_recognizeByCodeTypeAndPath(path, codeType, result);
            string resultCode = CheckResult(result.ToString(), Const.SOFTID, codeId, Const.CHECKKEY);
            string str = string.Format("Code ID:{0}, 识别结果:{1}", codeId, resultCode.ToString());
            Log.PrintLog(str);
            return resultCode;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="DLLPath"></param>
        /// <returns></returns>
        public bool CheckApiSign(string DLLPath)
        {
            bool suc = false;
            int softId = Const.SOFTID;
            string softKey = Const.SOFTKEY;
            Guid guid = Guid.NewGuid();
            string strGuid = guid.ToString().Replace("-", "").Substring(0, 32).ToUpper();
            //string DLLPath = "E:\\work\\UUWiseHelper 新版http协议\\输出目录\\UUWiseHelper.dll";
            string strDllMd5 = GetFileMD5(DLLPath);
            CRC32 objCrc32 = new CRC32();
            string strDllCrc = String.Format("{0:X}", objCrc32.FileCRC(DLLPath));
            //CRC不足8位，则前面补0，补足8位
            int crcLen = strDllCrc.Length;
            if (crcLen < 8)
            {
                int miss = 8 - crcLen;
                for (int i = 0; i < miss; ++i)
                {
                    strDllCrc = "0" + strDllCrc;
                }
            }
            //下面是软件id对应的dll校验key。在开发者后台-我的软件里面可以查的到。
            string strCheckKey = Const.CHECKKEY.ToUpper();
            string yuanshiInfo = softId.ToString() + strCheckKey + strGuid + strDllMd5.ToUpper() + strDllCrc.ToUpper();
            string localInfo = MD5Encoding(yuanshiInfo);
            StringBuilder checkResult = new StringBuilder();
            Wrapper.uu_CheckApiSign(softId, softKey, strGuid, strDllMd5, strDllCrc, checkResult);
            string strCheckResult = checkResult.ToString();
            if (localInfo.Equals(strCheckResult))
            {
                suc = true;
            }
            else
            {
                Log.PrintLog(TAG + " ： Dll校验失败！服务器返回信息为" + strCheckResult + "本地校验信息为" + localInfo + "\n");
            }
            return suc;
        }

        #region 校验工具
        /// <summary>
        /// 获取文件MD5校验值
        /// </summary>
        /// <param name="filePath">校验文件路径</param>
        /// <returns>MD5校验字符串</returns>
        private static string GetFileMD5(string filePath)
        {
            FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            byte[] md5byte = md5.ComputeHash(fs);
            int i, j;
            StringBuilder sb = new StringBuilder(16);
            foreach (byte b in md5byte)
            {
                i = Convert.ToInt32(b);
                j = i >> 4;
                sb.Append(Convert.ToString(j, 16));
                j = ((i << 4) & 0x00ff) >> 4;
                sb.Append(Convert.ToString(j, 16));
            }
            if (fs != null)
            {
                fs.Close();
                fs = null;
            }
            return sb.ToString();
        }
        



        /// <summary>
        /// MD5 加密字符串
        /// </summary>
        /// <param name="rawPass">源字符串</param>
        /// <returns>加密后字符串</returns>
        public static string MD5Encoding(string rawPass)
        {
            // 创建MD5类的默认实例：MD5CryptoServiceProvider
            MD5 md5 = MD5.Create();
            byte[] bs = Encoding.UTF8.GetBytes(rawPass);
            byte[] hs = md5.ComputeHash(bs);
            StringBuilder sb = new StringBuilder();
            foreach (byte b in hs)
            {
                // 以十六进制格式格式化
                sb.Append(b.ToString("x2"));
            }
            return sb.ToString();
        }

        public static string CheckResult(string result, int softId, int codeId, string checkKey)
        {
            //对验证码结果进行校验，防止dll被替换
            if (string.IsNullOrEmpty(result))
                return result;
            else
            {
                if (result[0] == '-')
                    //服务器返回的是错误代码
                    return result;

                string[] modelReult = result.Split('_');
                //解析出服务器返回的校验结果
                string strServerKey = modelReult[0];
                string strCodeResult = modelReult[1];
                //本地计算校验结果
                string localInfo = softId.ToString() + checkKey + codeId.ToString() + strCodeResult.ToUpper();
                string strLocalKey = MD5Encoding(localInfo).ToUpper();
                //相等则校验通过
                if (strServerKey.Equals(strLocalKey))
                    return strCodeResult;
                return "结果校验不正确";
            }
        }

        #endregion
    }
}
